/*
 * Copyright (c) 2024 iSOFT INFRASTRUCTURE SOFTWARE CO., LTD.
 * easyAda is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */

#ifndef __ASSEMBLER_DEFINE_H__
#define __ASSEMBLER_DEFINE_H__

#define EXCEPTION_STACK_SIZE 4 * 1024

#define S_FRAME_SIZE 272 /* sizeof(struct pt_regs) */
#define S_X0         0   /* offsetof(struct pt_regs, regs[0]) */
#define S_X1         8   /* offsetof(struct pt_regs, regs[1]) */
#define S_X2         16  /* offsetof(struct pt_regs, regs[2]) */
#define S_X3         24  /* offsetof(struct pt_regs, regs[3]) */
#define S_X4         32  /* offsetof(struct pt_regs, regs[4]) */
#define S_X5         40  /* offsetof(struct pt_regs, regs[5]) */
#define S_X6         48  /* offsetof(struct pt_regs, regs[6]) */
#define S_X7         56  /* offsetof(struct pt_regs, regs[7]) */
#define S_X8         64  /* offsetof(struct pt_regs, regs[8]) */
#define S_X10        80  /* offsetof(struct pt_regs, regs[10]) */
#define S_X12        96  /* offsetof(struct pt_regs, regs[12]) */
#define S_X14        112 /* offsetof(struct pt_regs, regs[14]) */
#define S_X16        128 /* offsetof(struct pt_regs, regs[16]) */
#define S_X18        144 /* offsetof(struct pt_regs, regs[18]) */
#define S_X20        160 /* offsetof(struct pt_regs, regs[20]) */
#define S_X22        176 /* offsetof(struct pt_regs, regs[22]) */
#define S_X24        192 /* offsetof(struct pt_regs, regs[24]) */
#define S_X26        208 /* offsetof(struct pt_regs, regs[26]) */
#define S_X28        224 /* offsetof(struct pt_regs, regs[28]) */
#define S_FP         232 /* offsetof(struct pt_regs, regs[29]) */
#define S_LR         240 /* offsetof(struct pt_regs, regs[30]) */
#define S_SP         248 /* offsetof(struct pt_regs, sp) */
#define S_PC         256 /* offsetof(struct pt_regs, pc) */
#define S_PSTATE     264 /* offsetof(struct pt_regs, pstate) */

#define BEGIN_FUNC(_name)      \
    .global _name;             \
    .type   _name, % function; \
_name:

#define END_FUNC(_name)        \
    .size _name, .-_name

#define BEGIN_BOOT_FUNC(_name) \
    .global _name;             \
    .type   _name, % function; \
_name:


#define BEGIN_VECTOR(_name)    \
    .global _name;             \
    .type   _name, % function; \
_name:

#define END_VECTOR(_name)      \
    .size _name, .-_name


#endif

#ifdef __ASSEMBLER__


.macro adr_l, dst, sym
    adrp    \dst, \sym
    add     \dst, \dst, :lo12:\sym
.endm


.macro dcache op
    dsb     sy
    mrs     x0, clidr_el1
    and     x3, x0, #0x7000000
    lsr     x3, x3, #23

    cbz     x3, finished_\op
    mov     x10, #0

loop1_\op:
    add     x2, x10, x10, lsr #1
    lsr     x1, x0, x2
    and     x1, x1, #7
    cmp     x1, #2
    b.lt    skip_\op

    msr     csselr_el1, x10
    isb

    mrs     x1, ccsidr_el1
    and     x2, x1, #7
    add     x2, x2, #4
    mov     x4, #0x3ff
    and     x4, x4, x1, lsr #3
    clz     w5, w4
    mov     x7, #0x7fff
    and     x7, x7, x1, lsr #13

loop2_\op:
    mov     x9, x4

loop3_\op:
    lsl     x6, x9, x5
    orr     x11, x10, x6
    lsl     x6, x7, x2
    orr     x11, x11, x6
    dc      \op, x11
    subs    x9, x9, #1
    b.ge    loop3_\op
    subs    x7, x7, #1
    b.ge    loop2_\op

skip_\op:
    add     x10, x10, #2
    cmp     x3, x10
    b.gt    loop1_\op

finished_\op:
    mov     x10, #0
    msr     csselr_el1, x10
    dsb     sy
    isb
.endm

#else /* !__ASSEMBLER__ */
#warning "Including assembly-specific header in C code"
#endif
